package com.bizmda.bizsip.common;

import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONStrFormatter;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.UnsupportedEncodingException;
import java.util.concurrent.*;

/**
 * @author 史正烨
 */
@Slf4j
public class BizUtils {
    public static final ThreadLocal<BizMessage<JSONObject>> bizMessageThreadLocal = new ThreadLocal<>();
    public static final ThreadLocal<TmContext> tmContextThreadLocal = new ThreadLocal<>();
    private static final ExecutorService elExecutorService = ThreadUtil.newExecutor(Runtime.getRuntime().availableProcessors());

    private BizUtils() {
    }

    public static String getElStringResult(String express, Object data) throws BizException {
        String result = null;
        Future<Object> future = elExecutorService.submit(new ElThread(express,data,false));
        try {
            result = (String)future.get();
        } catch (InterruptedException e) {
            log.error("EL表达式计算被中断:{}",express,e);
            Thread.currentThread().interrupt();
            return null;
        } catch (ExecutionException e) {
            throw new BizException(BizResultEnum.EL_CALCULATE_ERROR,e,
                    StrFormatter.format("EL表达式计算出错:{}",express));
        }
        return result;
    }

    public static Boolean getElBooleanResult(String express, Object data) throws BizException {
        Boolean result = null;
        Future<Object> future = elExecutorService.submit(new ElThread(express,data,true));
        try {
            result = (Boolean)future.get();
        } catch (InterruptedException e) {
            log.error("EL表达式计算被中断:{}",express,e);
            Thread.currentThread().interrupt();
            return false;
        } catch (ExecutionException e) {
            throw new BizException(BizResultEnum.EL_CALCULATE_ERROR,e,
                    StrFormatter.format("EL表达式计算出错:{}",express));
        }
        return result;
    }

    public static byte[] getBytes(String str) throws BizException {
        try {
            return str.getBytes(BizConstant.DEFAULT_CHARSET_NAME);
        } catch (UnsupportedEncodingException e) {
            throw new BizException(BizResultEnum.UNSUPPORTED_ENCODING_ERROR,e);
        }
    }

    public static String getString(byte[] bytes) throws BizException {
        try {
            return new String(bytes,BizConstant.DEFAULT_CHARSET_NAME);
        } catch (UnsupportedEncodingException e) {
            throw new BizException(BizResultEnum.UNSUPPORTED_ENCODING_ERROR,e);
        }
    }

    public static String buildJsonLog(Object jsonObject) {
        if (jsonObject instanceof String) {
            return JSONStrFormatter.format((String)jsonObject);
        }
        else {
            return JSONUtil.toJsonPrettyStr(jsonObject);
        }
    }

    public static String buildHexLog(byte[] bytes) {
        byte[] rightBytes = new byte[20];
        StringBuilder stringBuilder = new StringBuilder("====+ 01-02-03-04-05-06-07-08-09-10-11-12-13-14-15-16-17-18-19-20 + ====== ASCII  ====== +\n");
        int i;
        for(i = 0;i<bytes.length;i++) {
            if (i%20 == 0) {
                for(int j=0;j<20;j++) {
                    rightBytes[j] = '.';
                }
                stringBuilder.append(StrUtil.fill(String.valueOf(i),'0',4,true));
                stringBuilder.append(':');
            }
            stringBuilder.append(' ');
            HexUtil.appendHex(stringBuilder,bytes[i],false);
            if (bytes[i] >= 0x20 || bytes[i] < 0) {
                rightBytes[i%20] = bytes[i];
            }
            if ((i+1)%20 == 0) {
                stringBuilder.append(" | ");
                try {
                    appendRightBytes(stringBuilder,rightBytes);
                    stringBuilder.append(" |");
                } catch (BizException e) {
                    e.printStackTrace();
                }
                stringBuilder.append("\n");
            }
        }

        for(int j = i%20;j<20;j++) {
            stringBuilder.append("   ");
        }
        if (i%20 != 0) {

            stringBuilder.append(" | ");
            try {
                appendRightBytes(stringBuilder,rightBytes);
                stringBuilder.append(" |");
            } catch (BizException e) {
                e.printStackTrace();
            }
            stringBuilder.append("\n");
        }
        return stringBuilder.toString();
    }

    private static void appendRightBytes(StringBuilder stringBuilder,byte[] bytes) throws BizException {
        char[] ch = BizUtils.getString(bytes).toCharArray();
        for(int i = 0;i<ch.length;i++) {
            stringBuilder.append(ch[i]);
            if (isChinese(ch[i])) {
                stringBuilder.append(".");
            }
        }
        return;
    }

    private static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);

        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS

                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS

                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A

                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B

                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION

                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS

                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
            return true;
        }
        return false;
    }

}
